package cn.com.ejiakanghu.service;

import cn.com.ejiakanghu.core.config.DirectExchangeRabbitMQConfig;
import cn.com.ejiakanghu.core.config.WechatConstant;
import cn.com.ejiakanghu.core.exception.CheckException;
import cn.com.ejiakanghu.core.rabbitmq.DirectExchangeProducer;
import cn.com.ejiakanghu.task.RefusedOrderTask;
import cn.ejiakanghu.logistics.service.TakeOrderService;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.linlinjava.litemall.core.task.TaskService;
import org.linlinjava.litemall.db.dao.AgedmallLgBaseInfoMapper;
import org.linlinjava.litemall.db.dao.AgedmallLgMissionMapper;
import org.linlinjava.litemall.db.dao.AgedmallLgReceiveOrderMapper;
import org.linlinjava.litemall.db.dao.AgedmallTakeOrderRecordMapper;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.wechat_notice.WechatNoticeService;
import org.linlinjava.litemall.db.util.LgBaseInfoLgType;
import org.linlinjava.litemall.db.util.LogisticsMissionTypeEnum;
import org.linlinjava.litemall.db.vo.wechat.ApplicationCardMessage;
import org.linlinjava.litemall.db.vo.wechat.GetTextContent;
import org.linlinjava.litemall.db.vo.wechat.ReceivedBean;
import org.linlinjava.litemall.db.vo.wechat.TextCardDescMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author wj
 * @date 2021/10/19 17:04
 */
@Service
public class EnterpriseWeChatService {
    private Logger logger = LoggerFactory.getLogger(EnterpriseWeChatService.class);

    @Resource
    private WechatNoticeService wechatNoticeService;

    @Resource
    private DirectExchangeProducer directExchangeProducer;


    @Resource
    private TaskService taskService;

    @Resource
    private AgedmallTakeOrderRecordMapper agedmallTakeOrderRecordMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private TakeOrderService takeOrderService;

    @Resource
    private AgedmallLgMissionMapper agedmallLgMissionMapper;

    @Resource
    private AgedmallLgBaseInfoMapper agedmallLgBaseInfoMapper;

    @Resource
    private NoticeService noticeService;

    @Resource
    private AgedmallLgReceiveOrderMapper agedmallLgReceiveOrderMapper;

    @Resource
    private cn.ejiakanghu.logistics.service.impl.LogisticBusiBaseServiceImpl logisticBusiBaseServiceImpl;


    /**
     * 分包后发送企业微信/通知播报器
     */
    public void sendNotice(Integer missionId){
        AgedmallLgMission mission=agedmallLgMissionMapper.selectByPrimaryKey(missionId);
        Integer sleepCount=0;
        while (ObjectUtil.isNull(mission)&&sleepCount<5){
            try {
                Thread.sleep(1000);
                mission=agedmallLgMissionMapper.selectByPrimaryKey(missionId);
            } catch (InterruptedException e) {
                logger.error("发送通知线程睡眠错误:{}",missionId);
                throw new RuntimeException();
            }
            finally {
                sleepCount++;
            }

        }
        AgedmallLgBaseInfo lgBaseInfo = agedmallLgBaseInfoMapper.selectByPrimaryKey(mission.getBaseInfoId().longValue());
        if(lgBaseInfo.getNoticeType()==1){
            //如果是企业微信抢单 建立相关表
            List<AgedmallTakeOrderRecord> records=takeOrderService.addNoticeData(mission,lgBaseInfo);
            if(!records.isEmpty()){
                //顺序抢单
                if(records.get(0).getType()==0){
                    sendTemplateCardNotice(records.get(0).getId());
                }
                //一起抢单
                else{
                    for (AgedmallTakeOrderRecord record:records) {
                        sendTemplateCardNotice(record.getId());
                    }
                }
            }
        }
        else{
            // TODO 播报器直接接单
            //如果是云仓，直接增加配货员
            if(mission.getType().equals(LogisticsMissionTypeEnum.ALLOT.getCode())){
            logisticBusiBaseServiceImpl.isCloudOrder(lgBaseInfo.getId().intValue(),missionId);
            }
            //播报机发送通知声音
            try {
                noticeService.send(mission.getId(),"-1",null);
            } catch (Exception e) {
                logger.error("发送播报器错误，任务id：{}，错误为：",mission.getId(),e);
            }
        }

    }

    /**
     * 通知医生消息
     */
    public void sendDoctorNotice(Long serviceOrderId){
        List<AgedmallTakeOrderRecord> takeOrderRecords = takeOrderService.addDoctoNoticerData(serviceOrderId);
        sendTemplateCardNotice(takeOrderRecords.get(0).getId());
    }




    /**
     * 发送个人按钮模板消息
     *
     * @param id takeOrderId
     */
    public void sendTemplateCardNotice(Long id) {
        ReceivedBean receivedBean = new ReceivedBean();
        ApplicationCardMessage applicationCardMessage = wechatNoticeService.sendNotice(id);
        receivedBean.setType(0);
        receivedBean.setApplicationCardMessage(applicationCardMessage);
        String responseCode = (String) directExchangeProducer.send(JSONUtil.toJsonStr(receivedBean), DirectExchangeRabbitMQConfig.TO_WECHAT_NOTICE);
        stringRedisTemplate.opsForValue().set(WechatConstant.TEMPLATE_RESPONSE_CODE_REDIS_KEY + id.toString(), responseCode, 12, TimeUnit.MINUTES);
        //加入定时任务
        taskService.addTask(new RefusedOrderTask(id.intValue(), responseCode));
        //修改TakeOrder状态
        AgedmallTakeOrderRecord takeOrderRecord=agedmallTakeOrderRecordMapper.selectByPrimaryKey(id);
        takeOrderRecord.setState(1);
        agedmallTakeOrderRecordMapper.updateByPrimaryKey(takeOrderRecord);
    }


    /**
     * 按钮模板按钮-拒绝/超时拒绝
     *
     * @param id        takeOrderId
     * @param isTimeOut 是否超时拒绝
     */
    public void refused(Long id, boolean isTimeOut, String responseCode) {
        AgedmallTakeOrderRecord record=agedmallTakeOrderRecordMapper.selectByPrimaryKey(id);
        if(record == null) {
            logger.error("refused获取记录为空{}",id);
            return;
        }
        //检查订单
        boolean check = checkOrderState(record);
        if(!check){
            logger.error("refused检查订单状态失败:{}",id);
            return;
        }
        Long nextId=wechatNoticeService.refused(id, isTimeOut);
        if(nextId != null){
            //发送给下一个人
            sendTemplateCardNotice(nextId);
        }
        else{
            List<Integer> stateList=new ArrayList<>();
            stateList.add(4);
            stateList.add(2);
            AgedmallTakeOrderRecordExample nextExample=new AgedmallTakeOrderRecordExample();
            nextExample.setOrderByClause("`delivery_man_id` asc");
            nextExample.or().andPrintIdEqualTo(record.getPrintId()).andStateIn(stateList);
            List<AgedmallTakeOrderRecord> orderRecordList = agedmallTakeOrderRecordMapper.selectByExample(nextExample);
            List<Integer> ids=new ArrayList<>();
            orderRecordList.forEach(orderRecord ->
                    {
                        if(ids.size()==0){
                            ids.add(orderRecord.getDeliveryManId());
                        }
                        else if(!ids.contains(orderRecord.getDeliveryManId())){
                            ids.add(orderRecord.getDeliveryManId());
                        }
                    }
                    );
            //如果重复了两遍
            if(orderRecordList.size()>ids.size()*2){
                //TODO 这边通知无人接单
                logger.error("接单次数超限，无人接单：{}",id);
            }
            else{
                logger.error("开始循环重复接单:{}",ids);
                List<AgedmallTakeOrderRecord> newRecordList = wechatNoticeService.add(record.getPrintId(), ids, orderRecordList.get(0).getType(), orderRecordList.get(0).getMessageType());
                //顺序抢单
                if(newRecordList.get(0).getType()==0){
                    sendTemplateCardNotice(newRecordList.get(0).getId());
                }
                //一起抢单
                else{
                    for (AgedmallTakeOrderRecord newRecord:newRecordList) {
                        sendTemplateCardNotice(newRecord.getId());
                    }
                }
            }
        }
        //模板不可选中
        ReceivedBean receivedBean = new ReceivedBean();
        receivedBean.setType(1);
        receivedBean.setResponseCode(responseCode);
        if (isTimeOut) {
            receivedBean.setButtonMsg("已超时");
        } else {
            receivedBean.setButtonMsg("已拒绝");
        }
        directExchangeProducer.send(JSONUtil.toJsonStr(receivedBean), DirectExchangeRabbitMQConfig.TO_WECHAT_NOTICE);
    }


    /**
     * 按钮模板按钮-同意接单
     *
     * @param id
     */
    public void confirm(Long id) {
        AgedmallTakeOrderRecord record = agedmallTakeOrderRecordMapper.selectByPrimaryKey(id);
        //检查订单
        boolean check = checkOrderState(record);
        if(!check){
            logger.error("confirm接单检查错误：{}",id);
            return;
        }
        AgedmallTakeOrderRecordExample recordExample = new AgedmallTakeOrderRecordExample();
        recordExample.or().andPrintIdEqualTo(record.getPrintId());
        List<AgedmallTakeOrderRecord> agedmallTakeOrderRecords = agedmallTakeOrderRecordMapper.selectByExample(recordExample);
        List<AgedmallTakeOrderRecord> collect = agedmallTakeOrderRecords.stream().filter(takeOrder -> takeOrder.getState() == 3).collect(Collectors.toList());
        logger.info("查看是否已经有人接单：{}",collect.isEmpty());
        if (collect.isEmpty()) {
            logger.info("没有人接单已判断：{}",record.getId());
            String redisKey = WechatConstant.TEMPLATE_RESPONSE_CODE_REDIS_KEY + record.getId().toString();
            String code = stringRedisTemplate.opsForValue().get(redisKey);
            if (StrUtil.isNotBlank(code)) {
                logger.info("当前模板返回码已判断：{}",record.getId());
                wechatNoticeService.confirm(id);
                //控制模板变为不可用
                ReceivedBean receivedBean = new ReceivedBean();
                receivedBean.setType(1);
                receivedBean.setResponseCode(code);
                receivedBean.setButtonMsg("接单成功");
                directExchangeProducer.send(JSONUtil.toJsonStr(receivedBean), DirectExchangeRabbitMQConfig.TO_WECHAT_NOTICE);
                stringRedisTemplate.delete(redisKey);

                //修改物流相关表状态
                takeOrderService.takeOrderStatChangeWechat(record.getId());

                //卡片消息
                TextCardDescMessage textCardDescMessage = wechatNoticeService.sendTextCardMessage(record.getId());
                ReceivedBean textCardBean = new ReceivedBean();
                textCardBean.setType(2);
                textCardBean.setTextCardDescMessage(textCardDescMessage);
                directExchangeProducer.send(JSONUtil.toJsonStr(textCardBean), DirectExchangeRabbitMQConfig.TO_WECHAT_NOTICE);
                //文字消息
                GetTextContent getTextContent = new GetTextContent();
                getTextContent.setChatId(textCardDescMessage.getChatId());
                getTextContent.setContent(wechatNoticeService.switchTextMessage(record.getMessageType()));
                ReceivedBean textBean = new ReceivedBean();
                textBean.setType(3);
                textBean.setGetTextContent(getTextContent);
                directExchangeProducer.send(JSONUtil.toJsonStr(textBean), DirectExchangeRabbitMQConfig.TO_WECHAT_NOTICE);
            }
        }
        AgedmallTakeOrderRecordExample isRobTakeOrder = new AgedmallTakeOrderRecordExample();
        isRobTakeOrder.or().andPrintIdEqualTo(record.getPrintId()).andStateNotEqualTo(3).andStateNotEqualTo(2).andStateNotEqualTo(4);
        List<AgedmallTakeOrderRecord> tempalteOrderRecord = agedmallTakeOrderRecordMapper.selectByExample(isRobTakeOrder);
        AgedmallTakeOrderRecord takeOrderRecord = new AgedmallTakeOrderRecord();
        takeOrderRecord.setState(5);
        agedmallTakeOrderRecordMapper.updateByExampleSelective(takeOrderRecord, isRobTakeOrder);
        //控制模板变为不可用
        for (int i = 0; i < tempalteOrderRecord.size(); i++) {
            String redisKey = WechatConstant.TEMPLATE_RESPONSE_CODE_REDIS_KEY + tempalteOrderRecord.get(i).getId().toString();
            String code = stringRedisTemplate.opsForValue().get(redisKey);
            if (StrUtil.isNotBlank(code)) {
                ReceivedBean receivedBean = new ReceivedBean();
                receivedBean.setType(1);
                receivedBean.setResponseCode(code);
                receivedBean.setButtonMsg("已被接单");
                directExchangeProducer.send(JSONUtil.toJsonStr(receivedBean), DirectExchangeRabbitMQConfig.TO_WECHAT_NOTICE);
                stringRedisTemplate.delete(redisKey);
            }

        }
    }


    public boolean checkOrderState(AgedmallTakeOrderRecord record){
        if(record.getMessageType()==4){

        }
        else{
            AgedmallLgMission mission=agedmallLgMissionMapper.selectByPrimaryKey(record.getPrintId());
            AgedmallLgBaseInfo lgBaseInfo=agedmallLgBaseInfoMapper.selectByPrimaryKey(mission.getBaseInfoId().longValue());
            //检查订单是否可以继续
            try {
                logisticBusiBaseServiceImpl.checkLgBaseOrderStat(lgBaseInfo.getOrderCode());
                if(lgBaseInfo.getLgType().equals(LgBaseInfoLgType.GIVEBACK.getCode())){
                    logisticBusiBaseServiceImpl.checkBackIsCancel(lgBaseInfo.getLgIsOver());
                }

            } catch (CheckException e) {
                logger.error("当前订单/归还已被取消：{}",lgBaseInfo.getId());
                String redisKey = WechatConstant.TEMPLATE_RESPONSE_CODE_REDIS_KEY + record.getId().toString();
                String code = stringRedisTemplate.opsForValue().get(redisKey);
                if (StrUtil.isNotBlank(code)) {
                    //控制模板变为不可用
                    ReceivedBean receivedBean = new ReceivedBean();
                    receivedBean.setType(1);
                    receivedBean.setResponseCode(code);
                    receivedBean.setButtonMsg("已取消");
                    directExchangeProducer.send(JSONUtil.toJsonStr(receivedBean), DirectExchangeRabbitMQConfig.TO_WECHAT_NOTICE);
                    stringRedisTemplate.delete(redisKey);
                }
                return false;
            }
        }
        return true;
    }
}
